#ifndef DSPSIMULATOR_REGISTERKIND_H
#define DSPSIMULATOR_REGISTERKIND_H

#include <string>
#include <algorithm>
#include "simulator/type/type.h"

enum class RegKind {
    A0 = 0,
    A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15,
    A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31,
    B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15,
    B16, B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27, B28, B29, B30, B31,
    AMR,    // Addressing mode register
    CSR,        // Control status register
    GFPGFR,     // Galois field multiply control register
    ICR,        // Interrupt clear register
    IER,        // Interrupt enable register
    IFR,        // Interrupt flag register
    IRP,        // Interrupt return pointer register
    ISR,        // Interrupt set register
    ISTP,       // Interrupt service table pointer register
    NRP,        // Nonmaskable interrupt return pointer register
    PCE1,       // Program counter, E1 phase
    /// Control Register File Extensions
    DNUM,       // DSP core number register
    ECR,        // Exception clear register
    EFR,        // Exception flag register
    GPLYA,      // GMPY A-side polynomial register
    GPLYB,      // GMPY B-side polynomial register
    IERR,       // Internal exception report register
    ILC,        // Inner loop count register
    ITSR,       // Interrupt task state register
    NTSR,       // NMI/Exception task state register
    REP,        // Restricted entry point address register
    RILC,       // Reload inner loop count register
    SSR,        // Saturation status register
    TSCH,       // Time-stamp counter (high 32) register
    TSCL,       // Time-stamp counter (low 32) register
    TSR,        // Task state register
    /// Control Register File Extensions for Floating-point Operations
    FADCR,      // Floating-point adder configuration register
    FAUCR,      // Floating-point auxiliary configuration register
    FMCR,       // Floating-point multiplier configuration register
    Num_Of_Reg,
    UN_KNOWN
};

static const char *RegNames[] = {
        "A0", "A1", "A2", "A3",
        "A4", "A5", "A6", "A7",
        "A8", "A9", "A10", "A11",
        "A12", "A13", "A14", "A15",
        "A16", "A17", "A18", "A19",
        "A20", "A21", "A22", "A23",
        "A24", "A25", "A26", "A27",
        "A28", "A29", "A30", "A31",
        "B0", "B1", "B2", "B3",
        "B4", "B5", "B6", "B7",
        "B8", "B9", "B10", "B11",
        "B12", "B13", "B14", "B15",
        "B16", "B17", "B18", "B19",
        "B20", "B21", "B22", "B23",
        "B24", "B25", "B26", "B27",
        "B28", "B29", "B30", "B31",
        "AMR", "CSR", "GFPGFR", "ICR",
        "IER", "IFR", "IRP", "ISR",
        "ISTP", "NRP", "PCE1", "DNUM",
        "ECR", "EFR", "GPLYA", "GPLYB",
        "IERR", "ILC", "ITSR", "NTSR",
        "REP", "RILC", "SSR", "TSCH",
        "TSCL", "TSR", "FADCR", "FAUCR",
        "FMCR"
};

/**
 * 根据寄存器名获取寄存器类型
 * @param regName 寄存器名
 * @return 寄存器类型
 */
static RegKind getRegKind(std::string regName) {
    std::transform(regName.begin(), regName.end(), regName.begin(), ::toupper);
    for (u32 i = 0; i < static_cast<u32>(RegKind::Num_Of_Reg); ++i) {
        if (RegNames[i] == regName) {
            return static_cast<RegKind>(i);
        }
    }
    return RegKind::UN_KNOWN;
}

/**
 * 根据寄存器类型获取寄存器名
 * @param regKind 寄存器类型
 * @return 寄存器名
 */
static std::string getRegName(RegKind regKind) {
    if (regKind >= RegKind::Num_Of_Reg) {
        return {"UN_KNOWN"};
    }

    u32 regIndex = static_cast<u32>(regKind);
    return RegNames[regIndex];
}

#endif //DSPSIMULATOR_REGISTERKIND_H
